package com.loren.oauth.web.controller;

import com.loren.oauth.data.dto.AccessTokenInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
import org.springframework.http.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Controller
@RequestMapping
@AllArgsConstructor
public class OauthResourceController {

	private final OAuth2ClientProperties oauth2ClientProperties;

	private static final String OAUTH_CALLBACK_URL = "http://127.0.0.1:8082/oauth/callback";

	@ResponseBody
	@GetMapping("/user-info")
	public Object userInfo() {
		return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	}

	@GetMapping("/oauth/authorize")
	public String oauthAuthorize() {
		String clientId = this.oauth2ClientProperties.getClientId();
		return "redirect:http://127.0.0.1:9600/oauth/authorize?response_type=code&client_id=" + clientId
				+ "&redirect_uri=" + OAUTH_CALLBACK_URL + "&state=abcd";
	}

	@ResponseBody
	@GetMapping("/oauth/callback")
	public Object oauthCallback(String code, String state) {
		log.info("code = {}, state = {}", code, state);
		String oauthAuthorizationUrl = "http://127.0.0.1:9600/oauth/token";
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
		headers.setBasicAuth(this.oauth2ClientProperties.getClientId(), this.oauth2ClientProperties.getClientSecret());
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("code", code);
		params.add("grant_type", "authorization_code");
		params.add("redirect_uri", OAUTH_CALLBACK_URL);
		RestTemplate restTemplate = new RestTemplate();
		HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
		ResponseEntity<AccessTokenInfo> accessTokenResponse = restTemplate.exchange(oauthAuthorizationUrl,
				HttpMethod.POST, entity, AccessTokenInfo.class);
		return accessTokenResponse.getBody();
	}
}
